"""
CPU range processor module
"""
from seleniumbase import SB
from models.database import CPU, GPU, Game, FPSPrediction
from sqlalchemy.orm import Session
from sqlalchemy import and_
from .data_fetcher import fetch_fps_data
import time
import logging

logger = logging.getLogger(__name__)

def get_last_processed_combination_in_range(session: Session, start_cpu_id: int, end_cpu_id: int) -> tuple:
    """
    获取指定 CPU 区间内最后处理的组合
    Args:
        session: 数据库会话
        start_cpu_id: 起始 CPU ID
        end_cpu_id: 结束 CPU ID
    Returns:
        Tuple[int, int, int]: (cpu_id, gpu_id, game_id) 或 None
    """
    result = session.query(
        FPSPrediction.cpu_id,
        FPSPrediction.gpu_id,
        FPSPrediction.game_id
    ).filter(
        and_(
            FPSPrediction.cpu_id >= start_cpu_id,
            FPSPrediction.cpu_id <= end_cpu_id
        )
    ).order_by(
        FPSPrediction.cpu_id.desc(),
        FPSPrediction.gpu_id.desc(),
        FPSPrediction.game_id.desc()
    ).first()
    
    if result:
        return (result.cpu_id, result.gpu_id, result.game_id)
    return None

def is_combination_processed(session: Session, cpu_id: int, gpu_id: int, game_id: int) -> bool:
    """
    检查特定组合是否已处理
    """
    exists_query = session.query(FPSPrediction).filter(
        and_(
            FPSPrediction.cpu_id == cpu_id,
            FPSPrediction.gpu_id == gpu_id,
            FPSPrediction.game_id == game_id
        )
    ).exists()
    return session.query(exists_query).scalar()

def process_cpu_range(session: Session, start_cpu_id: int, end_cpu_id: int):
    """
    处理指定范围内的 CPU 组合
    Args:
        session: 数据库会话
        start_cpu_id: 起始 CPU ID
        end_cpu_id: 结束 CPU ID
    """
    # Get all valid combinations
    cpus = session.query(CPU).filter(
        and_(
            CPU.status == 1,
            CPU.id >= start_cpu_id,
            CPU.id <= end_cpu_id
        )
    ).all()
    
    gpus = session.query(GPU).filter(GPU.status == 1).all()
    games = session.query(Game).filter(Game.status == 4).all()
    
    total_combinations = len(cpus) * len(gpus) * len(games)
    success_count = 0
    
    logger.info(f"Processing CPU range: {start_cpu_id} to {end_cpu_id}")
    logger.info(f"Total CPUs in range: {len(cpus)}")
    logger.info(f"Total combinations to process: {total_combinations}")
    
    # 检查区间内是否有已处理的记录
    last_combination = get_last_processed_combination_in_range(session, start_cpu_id, end_cpu_id)
    
    # Initialize SeleniumBase with Cloudflare bypass settings
    with SB(uc=True, test=True, locale="en") as sb:
        try:
            # 激活 CDP 模式，只激活一次
            sb.activate_cdp_mode()
            
            if last_combination:
                last_cpu_id, last_gpu_id, last_game_id = last_combination
                logger.info(f"Resuming from last processed combination: CPU ID {last_cpu_id}, GPU ID {last_gpu_id}, Game ID {last_game_id}")
                
                # 首先完成最后一个 CPU 的剩余组合
                current_cpu = session.query(CPU).filter(CPU.id == last_cpu_id).first()
                if current_cpu:
                    # 找到当前 GPU 和 Game 的起始索引
                    start_gpu_index = next((i for i, gpu in enumerate(gpus) if gpu.id >= last_gpu_id), 0)
                    start_game_index = next((i for i, game in enumerate(games) if game.id > last_game_id), 0)
                    
                    # 处理当前 CPU 的剩余组合
                    for gpu in gpus[start_gpu_index:]:
                        for game in games[start_game_index:]:
                            if fetch_fps_data(sb, current_cpu, gpu, game, session):
                                success_count += 1
                            time.sleep(2)
                        # 重置 game 索引
                        start_game_index = 0
                
                # 从下一个 CPU 开始处理
                start_cpu_index = next((i for i, cpu in enumerate(cpus) if cpu.id > last_cpu_id), len(cpus))
            else:
                # 如果没有已处理的记录，从第一个 CPU 开始
                start_cpu_index = 0
            
            # 处理剩余的 CPU
            for cpu in cpus[start_cpu_index:]:
                cpu_success_count = 0
                cpu_total = len(gpus) * len(games)
                logger.info(f"Processing CPU: {cpu.pure_name}")
                
                for gpu in gpus:
                    for game in games:
                        if fetch_fps_data(sb, cpu, gpu, game, session):
                            success_count += 1
                            cpu_success_count += 1
                        time.sleep(2)
                
                # Update CPU status if all combinations were processed successfully
                if cpu_success_count == cpu_total:
                    cpu.status = 3  # Mark as data retrieved
                    session.commit()
                    logger.info(f"Completed CPU {cpu.pure_name}: {cpu_success_count}/{cpu_total} combinations")
                else:
                    logger.warning(f"CPU {cpu.pure_name} partially completed: {cpu_success_count}/{cpu_total} combinations")
                
                # 每完成一个 CPU 显示总体进度
                progress_percentage = (success_count / total_combinations * 100)
                logger.info(f"Overall progress: {success_count}/{total_combinations} ({progress_percentage:.2f}%)")
                
        except Exception as e:
            logger.error(f"Error in process_cpu_range: {str(e)}") 